home *** CD-ROM | disk | FTP | other *** search
/ isnet Internet / Isnet Internet CD.iso / prog / hiz / 09 / 09.exe / adynware.exe / perl / lib / adynware / utility.pm < prev    next >
Encoding:
Perl POD Document  |  2000-04-08  |  14.6 KB  |  522 lines

  1. package utility;
  2. use strict;
  3. use adynware::utility_file;
  4.  
  5. my $HTML_HEADER_NORMAL = "HTTP/1.0 200 OK\nContent-type: text/html\n\n";
  6. my $HTML_HEADER_REDIRECT = "HTTP/1.0 301 Moved Temporarily\nMIME-Version: 1.0\nContent-Length: 0\nLocation: ";
  7.  
  8. my $__baseTime = time();
  9. my $__cacheDir = "(uninitialized)";
  10. my $__program = "";
  11. my $__verbose = 4;
  12. my $__logFast = 0;
  13. my $__logBuffer = "";
  14.  
  15. sub GetMaxCacheFileSize()
  16. {
  17.         return 100000;
  18. }
  19.  
  20. sub getStandardHtmlHeader
  21. {
  22.         return $HTML_HEADER_NORMAL;
  23. }
  24.  
  25. sub Init
  26. {
  27.         my($program, $verbose, $cacheDir, $inputPort, $outputHost, $outputPort) = @_;
  28.                 
  29.         if (defined $inputPort and $inputPort==$outputPort and $outputHost eq "127.0.0.1")
  30.         {
  31.                 Die("$program: infinite port loop:$inputPort");
  32.         }
  33.         ($__program, $__verbose, $__cacheDir) = ($program, $verbose, $cacheDir);
  34. }
  35.  
  36. sub LogInMemory
  37. {
  38.         my ($fast) = @_;
  39.         $__logFast = $fast;
  40.         LogFlush() unless $fast;
  41. }
  42.  
  43. sub Log
  44. {
  45.         my ($message) = @_;
  46.         $message =~ s/\n/\n\t/g;
  47.         my $timeStampedMessage = sprintf("%04d[%s] %s\n", ($__baseTime - time()), $__program, $message);
  48.         if ($__logFast)
  49.         {
  50.                 $__logBuffer .= $timeStampedMessage;
  51.         }
  52.         else
  53.         {
  54.                 print $timeStampedMessage;
  55.         } 
  56. }
  57.  
  58. sub LogFlush
  59. {
  60.         print $__logBuffer if $__logBuffer;
  61.         $__logBuffer = "";
  62. }
  63.  
  64. sub IsImage
  65. {
  66.         my($fileName) = @_;
  67.         return ($fileName =~ /\.(gif|jpg)(\.new)?$/i);
  68. }
  69.  
  70. sub Read
  71. {
  72.         my($caller, $input, $buffer, $length) = @_;
  73.         my $n = undef;
  74.         while()
  75.         {
  76.                 #utility::Log("utility::Read about to call sys read");
  77.                 $n = sysread($input, $$buffer, $length); 
  78.                 #utility::Log("utility::Read back from sys read");
  79.                 
  80.                 last unless (!defined $n) and $! =~ /^Interrupted/;
  81.         } 
  82.         if ((!defined $n) or ($n < 0))
  83.         {
  84.                 Log("__Read from $caller: sysread:$!");
  85.                 return 0;
  86.         }
  87.                                                         
  88.         Log("just read $n bytes") if $__verbose >= 10;
  89.         return $n;
  90. }
  91.  
  92.  
  93. sub Write
  94. {
  95.         my($caller, $output, $buffer, $length) = @_;
  96.         my $offset = 0;
  97.         while()
  98.         {
  99.                 my $n = syswrite($output, $buffer, $length, $offset); 
  100.                 next if (!defined $n) and $! =~ /^Interrupted/;
  101.                 if ((!defined $n) or ($n < 0))
  102.                 {
  103.                         Log("__Write from $caller: syswrite:$!");
  104.                         return $offset;
  105.                 }
  106.                 Log("just wrote $n bytes");
  107.                 $length -= $n;
  108.                 $offset += $n;
  109.                 last unless $length>0;
  110.         }
  111.         return $offset;
  112. }
  113.  
  114.  
  115. sub SendRequest 
  116. {
  117.         my ($server, $clientRequest) = @_;
  118.     $clientRequest =~ s/^Accept-Encoding: gzip.*?\n//im;
  119.     Log("utility::SendRequest:$clientRequest") ;#if $__verbose >= 9;
  120.                                                         
  121.         my($savedSelectedFile) = select($server); $| = 1; select($savedSelectedFile);
  122.         $clientRequest =~ s/\n/\r\n/g;
  123.         $clientRequest =~ s/\r\r/\r/g;
  124.         print $server $clientRequest;
  125. }
  126.  
  127.  
  128. sub ReadHeader
  129. {
  130.         my($caller, $input) = @_;
  131.         my $buffer = "";
  132.         Log("ReadHeader reading") if $__verbose >= 8;
  133.         my $header = "";
  134.         my $consecutiveZeroByteReads = 0;
  135.         while()
  136.         {
  137.                 my $chunk;
  138.                 my $n = 0;
  139.                 $n = Read($caller, $input, \$chunk, 9184);
  140.                 if ($chunk eq "stop")
  141.                 {
  142.                         Log("utility::ReadHeader: shutdown request received.  Exiting...");
  143.                         LogFlush();
  144.                         exit(0);
  145.                 }
  146.                 $buffer .= $chunk;
  147.                 Log("ReadHeader has $buffer") if $__verbose >= 20;
  148.                 last if $buffer eq "prefetch";
  149.                 if ($buffer =~ s/(.*?\n\r?\n)//s)
  150.                 {
  151.                         $header = $1;
  152.                         $header =~ s/\r//g;
  153.                         last;
  154.                 }
  155.                 if ($n)
  156.                 {
  157.                         $consecutiveZeroByteReads = 0;
  158.                 }
  159.                 else
  160.                 {
  161.                         $consecutiveZeroByteReads++;
  162.                         last if ($consecutiveZeroByteReads > 10);
  163.                 } 
  164.         }
  165.         if ($header =~ /^post/i
  166.         and $header =~ /content-length: (\d+)/i)
  167.         {
  168.                 my $postedDataLength = $1;
  169.                 my $dataRead = length($buffer);
  170.                 while ($postedDataLength > $dataRead)
  171.                 {
  172.                         my $chunk;
  173.                         my $n = 0;
  174.                         $n = Read($caller, $input, \$chunk, 9184);
  175.                         Log("reading posted data: $dataRead read, got $n, need $postedDataLength") if $__verbose >= 10;
  176.                         if ($n)
  177.                         {
  178.                                 $buffer .= $chunk if $n;
  179.                                 $dataRead += $n;
  180.                                 $consecutiveZeroByteReads = 0;
  181.                         }
  182.                         else
  183.                         {
  184.                                 $consecutiveZeroByteReads++;
  185.                                 last if ($consecutiveZeroByteReads > 10);
  186.                         } 
  187.                 }
  188.         }
  189.               
  190.         Log("$caller called ReadHeader got $header") if $__verbose >= 4;
  191.         Log("ReadHeader saw posted data: $buffer") if $__verbose >= 20;
  192.         
  193.         return $header . $buffer;
  194. }
  195.  
  196. sub ReadFirstChunk
  197. {
  198.         my($caller, $server, $target, $referenceToExcess, $referenceContentType, $referenceContentLength, $suppressContentLength, $suppressDate) = @_;
  199.         my $serverResponse = utility::ReadHeader($caller, $server);
  200.         return undef unless $serverResponse;
  201.         my $header;
  202.         if ($serverResponse =~ s/(.*?\n\r?\n)//s)
  203.         {
  204.                 $header = $1;
  205.         }
  206.         else
  207.         {
  208.                 $header = $serverResponse;
  209.                 $serverResponse = "";
  210.         }
  211.                         
  212.         my $contentType;
  213.         if ($header =~ /^content-type:\s*(\S+)/im)
  214.         {
  215.                 $contentType = $1;
  216.         }
  217.         else
  218.         {
  219.                 $contentType = "image"; # we don't know what this is; resist the temptation to treat it as HTML to be modified
  220.         }
  221.         Log("content type is $contentType") if $__verbose >= 3;
  222.                 
  223.         if (defined $referenceContentLength)
  224.         {
  225.                 $$referenceContentLength = undef;
  226.                 if ($header =~ /^content-length:\s*(\d+)/im)
  227.                 {
  228.                         $$referenceContentLength = $1;
  229.                 }
  230.         } 
  231.         
  232.         if ($contentType =~ "text/html")
  233.         {
  234.                 $header =~ s/content-length.*\n//i if $suppressContentLength;
  235.                 $header =~ s/Date:.*\n//i          if $suppressDate;
  236.         }
  237.                                                          
  238.         $$referenceContentType = $contentType if defined $referenceContentType;
  239.         $$referenceToExcess = $serverResponse;
  240.         return $header;
  241. }
  242.  
  243.  
  244. sub LogState
  245. {
  246.         my($label, $handleKey, $stateReference) = @_;
  247.         my $message = "logging state: " . $label . " " . $handleKey . "=>";
  248.         if (!defined $stateReference)
  249.         {
  250.                 $message .= "(undefined)";
  251.         }
  252.         else
  253.         {
  254.                 my @state = @$stateReference;
  255.                 my $element;
  256.                 $message .= "[";
  257.                 my $j = 0;
  258.                 foreach $element (@state)
  259.                 {
  260.                         $j++;
  261.                         $message .= "," if $j > 1;
  262.                                                 
  263.                         if (defined $element)
  264.                         {
  265.                                 my $s = "";
  266.                                 $s .= $element;
  267.                                 $s =~ s/\n.*/.../s;
  268.                                 $s = "(long string)" if length($s) > 25;
  269.                                 $message .= $s;
  270.                         }
  271.                         else
  272.                         {
  273.                                 $message .= "undef";
  274.                         }
  275.                 }
  276.                 $message .= "]";
  277.         }
  278.         Log("$message") if $__verbose >= 9;
  279. }
  280.  
  281. sub GetCacheName
  282. {
  283.         my($queryFile) = @_;
  284.         
  285.         my $fileName = utility_file::flattenURL($queryFile);
  286.         
  287.         # allow 55 characters for the cache directory name
  288.         $fileName = substr($fileName, 0,  255 - 55) if (length($fileName) >=  255 - 55);
  289.  
  290.         return "$__cacheDir/$fileName";
  291. }
  292.  
  293. sub Die
  294. {
  295.         my($message) = @_;
  296.         print "utility::Die($message)\n";
  297.         executeAdynware("fatalError", $message);
  298.         die $message;
  299. }
  300.  
  301. sub TruncateForDisplay
  302. {
  303.         my($maximum, $s) = @_;
  304.         my $newS;
  305.         if (length($s) < $maximum)
  306.         {
  307.                 $newS = $s;
  308.         }
  309.         else
  310.         { 
  311.                 if ($maximum < 10)
  312.                 {
  313.                         $newS = "";
  314.                 }
  315.                 else
  316.                 {
  317.                         $newS = substr($s, 0, $maximum - 3) . "...";
  318.                 }
  319.         }
  320.         #print "truncate($maximum, $s) yielded $newS\n";
  321.         return $newS;
  322. }
  323.  
  324. sub packIPMask
  325. {
  326.         my($mask) = @_;
  327.     if ($mask !~ /^(\d+)(\.(\d+))?(\.(\d+))?(\.(\d+))?$/)
  328.     {
  329.         return $mask; # this is a host name or regexp, not a numeric IP @.  We cannot pack it.
  330.     }
  331.                         
  332.         my($b0, $b1, $b2, $b3) = ($1, $3, $5, $7);
  333.         my $packed;
  334.         if (!defined $b0)
  335.         {
  336.                 $packed = 0;
  337.         }
  338.         elsif (!defined $b1)
  339.         {
  340.                 $packed = pack("C1", $b0);
  341.         } 
  342.         elsif (!defined $b2)
  343.         {
  344.                 $packed = pack("C2", $b0, $b1);
  345.         } 
  346.         elsif (!defined $b3)
  347.         {
  348.                 $packed = pack("C3", $b0, $b1, $b2);
  349.         } 
  350.         else
  351.         {
  352.                 $packed = pack("C4", $b0, $b1, $b2, $b3);
  353.         }
  354.         
  355.         #printf "packIPMask(%s):%s\n", $mask, unpack("H" . (2 * length($packed)), $packed);
  356.         return $packed; 
  357. }
  358.  
  359. sub IPInMask
  360. {
  361.         my($i, $mask) = @_;
  362.         my $length = length($mask);
  363.         my $in = (substr($i, 0, $length) eq $mask);
  364.                                 
  365.         return $in;
  366. }
  367.  
  368. sub IPtoString
  369. {
  370.     my($ip) = @_;
  371.     return sprintf "%s", unpack("H8", $ip);
  372. }
  373.  
  374. sub IPInMaskSet
  375. {
  376.         my($host, @set) = @_;
  377.         return 0 unless scalar(@set); 
  378.         my($name, $aliases, $addressType, $length, @addresses) = gethostbyname($host);
  379.         foreach my $address (@addresses)
  380.         {
  381.                 foreach my $mask (@set)
  382.                 {
  383.             if ((($mask !~ /^[\w\*\.]+$/) && IPInMask($address, $mask))
  384.             || ($host =~ /^$mask$/))
  385.             {
  386.                                 Log("IPInMaskSet($host) should be accessed directly") if $__verbose >= 9; 
  387.                                 return 1;
  388.                         } 
  389.                 }
  390.         }
  391.         Log("IPInMaskSet($host) should be accessed through the proxy server") if $__verbose >= 9; 
  392.         return 0;
  393. }
  394.  
  395. sub constructIPMaskSet
  396. {
  397.         my($s) = @_;
  398.         my @strings = split(/;/, $s);
  399.         return constructIPMaskSetFromVector(@strings);
  400.  
  401. sub constructIPMaskSetFromVector
  402. {
  403.         my @strings = @_;
  404.     my @ipStrings = ();
  405.         my @ipSet = ();
  406.         foreach my $s (@strings)
  407.         {
  408.                 if ($s =~ /(\d+\.)+\d+/)
  409.                 {
  410.                         push(@ipStrings, $s);
  411.                 }
  412.                 else
  413.                 {
  414.             my(      $name, $aliases, $addressType, $length, @addresses);
  415.             if ($s !~ /\*/)
  416.             {
  417.                 ($name, $aliases, $addressType, $length, @addresses) = gethostbyname($s);
  418.             }
  419.             else
  420.             {
  421.                 $s = "." . $s if $s =~ /^\*/;   # convert sh regexp to perl, e.g., *.sun.com to .*.sun.com
  422.             }
  423.             my $message = "proxy exception $s will be accessed directly";
  424.             Log($message);
  425.                         
  426.             push(@ipSet, $s);
  427.                         if (scalar(@addresses))
  428.                         {
  429.                 Log("resolved proxy exception $s to " . @addresses . " addresses");
  430.                                 foreach my $address (@addresses)
  431.                                 {
  432.                     Log("resolved proxy exception $s to " . @addresses . " addresses, including " . IPtoString($address));
  433.                                         push(@ipSet, $address);
  434.                                 }                                                                  
  435.                         }                                                                  
  436.                 }
  437.         }
  438.                                 
  439.         foreach my $maskString (@ipStrings)
  440.         {
  441.                 my $i = utility::packIPMask($maskString);
  442.         if ($i)
  443.         {
  444.             Log("IP masking $maskString");
  445.             push(@ipSet, $i);
  446.         } 
  447.         else
  448.         {
  449.             Log("IP mask $maskString rejected");
  450.         }
  451.  
  452.         }
  453.         return @ipSet;
  454. }
  455.  
  456. sub executeAdynware
  457. {
  458.         my($flag, $arguments) = @_;
  459.         Log('system(' . "c:\\perl\\bin\\$__program.exe -$flag $arguments" . ')');
  460.         system("c:\\perl\\bin\\$__program.exe -$flag $arguments");
  461. sub unescape
  462. {
  463.         my($data) = @_;
  464.         $data =~ s/%([\da-fA-F][\da-fA-F])/'sprintf("%c", 0x' . $1 . ')'/eeg;
  465.         return $data;
  466. }
  467.  
  468. sub HandleAdynware
  469. {
  470.         my($client, $operation, $data) = @_;
  471.         $data = unescape($data);
  472.         my $redirectTarget = undef;
  473.         if ($operation eq "perl")
  474.         {
  475.                 Log("handle adynware: evaluating $data");
  476.                 eval($data);
  477.                 if ($@)
  478.                 {
  479.                         Log("eval failed:$@");
  480.                 }
  481.         }
  482.         else
  483.         {
  484.                 executeAdynware($operation, $data);
  485.         } 
  486.         answerBrowser($client, $redirectTarget);
  487.         return 1;
  488. }
  489.  
  490.  
  491. sub answerBrowser
  492. {
  493.         my($client, $redirectTarget) = @_;
  494.         if (defined $redirectTarget)
  495.         {
  496.                 print $client $HTML_HEADER_REDIRECT, $redirectTarget, "\n\n";
  497.         }
  498.         else
  499.         {
  500.                 print $client $HTML_HEADER_NORMAL, "<html> <body>";
  501.                 print $client "<script language='JavaScript'> onLoad=close; </script> ";
  502.                 print $client "</body> </html> ";
  503.         }
  504. }
  505.  
  506.  
  507. sub Spit
  508. {
  509.         my($port) = @_;
  510.         Log("about to attempt to shut down any server at $port.  This will result in an error message (IO::Socket::INET: Invalid argument) unless a server was already running there");
  511.         my $server = IO::Socket::INET->new(PeerAddr => "127.0.0.1", PeerPort => $port, Proto => 'tcp');
  512.         return unless $server;
  513.         Log("found a server; shutting it down");
  514.         print $server "stop";
  515.         close $server;
  516.         sleep 4;
  517. }
  518.  
  519. 1;
  520.